package com.xjd.transport.mock;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class NioServer {
	static Map<Channel, Thread> workers = new HashMap<Channel, Thread>();
	static Selector selector;

	public static void main(String[] args) throws IOException {
		selector = Selector.open();
		ServerSocketChannel server = ServerSocketChannel.open();
		server.socket().bind(new InetSocketAddress(9090));
		server.configureBlocking(false);
		
		server.register(selector, SelectionKey.OP_ACCEPT);
		
		while (true) {
			int n = selector.select();
			if (n > 0) {
				for (Iterator<SelectionKey> it = selector.selectedKeys().iterator(); it.hasNext();) {
					SelectionKey key = it.next();
					it.remove();
					
					if (!key.isValid()) {
						continue;
					}
					
					if (key.isAcceptable()) {
						SocketChannel client = ( (ServerSocketChannel)key.channel() ).accept();
						client.configureBlocking(false);
						client.register(selector, SelectionKey.OP_READ);
						
					} else if (key.isReadable()) {
						SocketChannel client = (SocketChannel) key.channel();
						
						synchronized (workers) {
							Thread worker = workers.get(client);
							if (worker == null || !worker.isAlive()) {
								System.out.println("New Worker: " + client);
								worker = new Worker(client, key);
								workers.put(client, worker);
								worker.start();
							}
						}
					}
				}
			}
		}
	}
	
	public static class Worker extends Thread {
		SocketChannel channel;
		SelectionKey key;
		
		public Worker(SocketChannel c, SelectionKey k) {
			channel = c;
			key = k;
		}
		
		public void run() {
			System.out.println("Worker Run: " + channel);
			
			ByteBuffer buf = ByteBuffer.allocate(1);
			int i;
			try {
				while ( (i = channel.read(buf)) != -1) {
					if (i > 0) {
						buf.flip();
						System.out.println(buf.get());
						buf.flip();
					} else {
						System.out.println(0);
					}
				}
			} catch (IOException e) {
				System.out.println(System.currentTimeMillis());
				e.printStackTrace();
			}
			
//			try {
//				Thread.sleep(5000);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
			
			System.out.println(channel.isConnected());
			System.out.println(channel.isOpen());
			try {
				key.cancel();
				channel.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
